package com.ruoyi.user.service.impl;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.user.domain.CouponTemplate;
import com.ruoyi.user.domain.UserCoupon;
import com.ruoyi.user.mapper.UserCouponMapper;
import com.ruoyi.user.service.IUserCouponService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class UserCouponServiceImpl implements IUserCouponService {

    @Autowired
    private UserCouponMapper userCouponMapper;

    @Override
    public UserCoupon selectUserCouponById(Long userCouponId) {
        return userCouponMapper.selectUserCouponById(userCouponId);
    }

    @Override
    public List<UserCoupon> selectUserCouponList(UserCoupon userCoupon) {
        return userCouponMapper.selectUserCouponList(userCoupon);
    }

    /**
     * 插入时默认走级联发券逻辑
     */
    @Override
    @Transactional
    public int insertUserCoupon(UserCoupon userCoupon) {
        return grantCouponToUser(userCoupon);
    }

    /**
     * 更新：若状态置为1（已用），走级联用券；否则走普通更新
     */
    @Override
    @Transactional
    public int updateUserCoupon(UserCoupon userCoupon) {
        if (userCoupon.getStatus() != null && userCoupon.getStatus() == 1) {
            return useCoupon(userCoupon);
        }
        return userCouponMapper.updateUserCoupon(userCoupon);
    }

    @Override
    public int deleteUserCouponByIds(Long[] userCouponIds) {
        return userCouponMapper.deleteUserCouponByIds(userCouponIds);
    }

    @Override
    public int deleteUserCouponById(Long userCouponId) {
        return userCouponMapper.deleteUserCouponById(userCouponId);
    }

    @Override
    public List<Map<String, Object>> selectUserCouponDetailListByCustomerId(Long customerId) {
        return userCouponMapper.selectUserCouponDetailListByCustomerId(customerId);
    }

    @Override
    public List<Map<String, Object>> selectUserCouponDetailListByCustomerIdAndStatus(Long customerId, Integer status) {
        return userCouponMapper.selectUserCouponDetailListByCustomerIdAndStatus(customerId, status);
    }

    @Override
    public List<Map<String, Object>> selectUserCouponDetailListByCustomerIdAndType(Long customerId, Integer type) {
        return userCouponMapper.selectUserCouponDetailListByCustomerIdAndType(customerId, type);
    }

    @Override
    public List<Map<String, Object>> selectUserCouponDetailList(UserCoupon userCoupon) {
        return userCouponMapper.selectUserCouponDetailList(userCoupon);
    }

    /**
     * 发券级联：校验模板有效性与容量，插入user_coupons记录
     */
    @Override
    @Transactional
    public int grantCouponToUser(UserCoupon userCoupon) {
        if (userCoupon.getCouponId() == null || userCoupon.getCustomerId() == null) {
            throw new IllegalArgumentException("couponId与customerId不能为空");
        }
        Long couponId = userCoupon.getCouponId();
        CouponTemplate meta = userCouponMapper.selectCouponTemplateMeta(couponId);
        if (meta == null || meta.getDeletedAt() != null) {
            throw new IllegalStateException("优惠券模板不存在或已删除");
        }
        if (meta.getStatus() == null || meta.getStatus() != 1) {
            throw new IllegalStateException("优惠券模板未启用");
        }
        Date now = DateUtils.getNowDate();
        if (meta.getValidFrom() != null && now.before(meta.getValidFrom())) {
            throw new IllegalStateException("优惠券尚未到有效期开始");
        }
        if (meta.getValidTo() != null && now.after(meta.getValidTo())) {
            throw new IllegalStateException("优惠券已过有效期");
        }

        // 容量校验：按已分配数量近似约束不超过总量
        int assignedCount = userCouponMapper.countAssignedByCouponId(couponId);
        if (meta.getTotalQuantity() != null && assignedCount >= meta.getTotalQuantity()) {
            throw new IllegalStateException("优惠券已发完");
        }

        // 组装插入记录
        if (userCoupon.getStatus() == null) {
            userCoupon.setStatus(0);
        }
        if (userCoupon.getAcquiredAt() == null) {
            userCoupon.setAcquiredAt(now);
        }
        if (userCoupon.getExpireAt() == null) {
            userCoupon.setExpireAt(meta.getValidTo());
        }
        userCoupon.setUpdatedAt(now);
        return userCouponMapper.insertUserCoupon(userCoupon);
    }

    /**
     * 用券级联：更新user_coupons为已用，递增模板used_quantity
     */
    @Override
    @Transactional
    public int useCoupon(UserCoupon userCoupon) {
        if (userCoupon.getUserCouponId() == null) {
            throw new IllegalArgumentException("userCouponId不能为空");
        }
        // 查询现有记录以做校验
        UserCoupon current = userCouponMapper.selectUserCouponById(userCoupon.getUserCouponId());
        if (current == null) {
            throw new IllegalStateException("用户优惠券不存在");
        }
        if (current.getStatus() != null && current.getStatus() != 0) {
            throw new IllegalStateException("当前优惠券状态不可用");
        }
        Date now = DateUtils.getNowDate();
        if (current.getExpireAt() != null && now.after(current.getExpireAt())) {
            throw new IllegalStateException("优惠券已过期");
        }
        // 模板容量校验（用于不超过总量）
        CouponTemplate meta = userCouponMapper.selectCouponTemplateMeta(current.getCouponId());
        if (meta == null || meta.getDeletedAt() != null) {
            throw new IllegalStateException("优惠券模板不存在或已删除");
        }
        if (meta.getUsedQuantity() != null && meta.getTotalQuantity() != null
                && meta.getUsedQuantity() >= meta.getTotalQuantity()) {
            throw new IllegalStateException("模板可用数量不足");
        }

        // 1) 更新user_coupons为已用
        UserCoupon patch = new UserCoupon();
        patch.setUserCouponId(current.getUserCouponId());
        patch.setStatus(1);
        patch.setUsedAt(now);
        patch.setUpdatedAt(now);
        int a = userCouponMapper.updateUserCoupon(patch);

        // 2) 递增模板used_quantity
        int b = userCouponMapper.incrementTemplateUsedQuantity(current.getCouponId());
        if (b == 0) {
            throw new IllegalStateException("模板用量更新失败或已达到上限");
        }
        return a;
    }
}
